package com.liuche.homechat.common.common.utils;

import cn.hutool.core.lang.TypeReference;
import cn.hutool.core.thread.NamedThreadFactory;
import cn.hutool.core.util.StrUtil;
import cn.hutool.extra.spring.SpringUtil;
import cn.hutool.http.HttpUtil;
import cn.hutool.json.JSONUtil;
import com.liuche.homechat.common.common.model.vo.resp.IpResult;
import com.liuche.homechat.common.user.cache.UserCache;
import com.liuche.homechat.common.user.dao.UserDao;
import com.liuche.homechat.common.user.domain.entity.IpDetail;
import com.liuche.homechat.common.user.domain.entity.IpInfo;
import com.liuche.homechat.common.user.domain.entity.User;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.ObjectUtils;

import java.util.Objects;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

/**
 * @author：liuche
 * @Date：2024年06月08日 15:05
 * @Description：关于 ip 的相关 service 方法
 */
//@Service
@Slf4j
public class IpUtil {
    private static final ExecutorService EXECUTOR = new ThreadPoolExecutor(1, 1,
            0L, TimeUnit.MILLISECONDS,
            new LinkedBlockingQueue<>(500),
            new NamedThreadFactory("refresh-ipDetail", null, false,
                    (t, e) -> log.error("Thread->【{}】；Exception-> 【{}】", t,e.getMessage())));
    private static final UserDao userDao;
    private static final UserCache userCache;

    static {
        userDao = SpringUtil.getBean(UserDao.class);
        userCache = SpringUtil.getBean(UserCache.class);
    }

    public static void refreshUserIp(User user) {
        EXECUTOR.execute(() -> {
            IpInfo ipInfo = user.getIpInfo();
            if (Objects.isNull(ipInfo)) {
                return;
            }
            String ip = ipInfo.needRefreshIp();
            if (StrUtil.isBlank(ip)) {
                return;
            }
            IpDetail ipDetail = TryGetIpDetailOrNullTreeTimes(ip);
            if (Objects.nonNull(ipDetail)) {
                ipInfo.refreshIpDetail(ipDetail);
                User update = new User();
                update.setId(user.getId());
                update.setIpInfo(ipInfo);
                userDao.updateById(update);
                // userCache.userInfoChange(user.getId()); // 用户信息缓存，后期做 todo
            } else {
                log.error("get ip detail fail ip:{},uid:{}", ip, user.getId());
            }

        });
    }


    private static IpDetail TryGetIpDetailOrNullTreeTimes(String ip) {
        for (int i = 0; i < 3; i++) {
            IpDetail ipDetail = getIpDetailOrNull(ip);
            if (Objects.nonNull(ipDetail)) {
                return ipDetail;
            }
            try {
                Thread.sleep(2000);
            } catch (InterruptedException e) {
                log.warn("异常信息", e);
            }
        }
        return null;
    }

    public static IpDetail getIpDetailOrNull(String ip) {
        String body = HttpUtil.get("https://ip.taobao.com/outGetIpInfo?ip=" + ip + "&accessKey=alibaba-inc");
        try {
            IpResult<IpDetail> result = JSONUtil.toBean(body, new TypeReference<IpResult<IpDetail>>() {
            }, false);
            if (result.isSuccess()) {
                return result.getData();
            }
        } catch (Exception ignored) {
            log.warn("获取 ip 信息失败");
        }
        return null;
    }

    /**
     * 构建用户的 ip 信息
     * @param user
     * @param ip
     * @return
     */
    public static IpInfo buildIpInfo(User user, String ip) {
        IpInfo ipInfo = user.getIpInfo();
        if (ObjectUtils.isEmpty(ipInfo)) {
            ipInfo = new IpInfo();
            ipInfo.setCreateIp(ip);
        }
        ipInfo.setUpdateIp(ip);

        return ipInfo;
    }
}
